package com.hbx.gift.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.hbx.gift.client.loginUserFeignClient;
import com.hbx.gift.constants.SmsContants;
import com.hbx.gift.domain.LoginUser;
import com.hbx.gift.domain.User;
import com.hbx.gift.domain.UserInfo;
import com.hbx.gift.dto.UserPhoneRegisterDto;
import com.hbx.gift.enums.SystemErrorCode;
import com.hbx.gift.exception.BusinessException;
import com.hbx.gift.mapper.UserInfoMapper;
import com.hbx.gift.mapper.UserMapper;
import com.hbx.gift.service.IUserService;
import com.hbx.gift.util.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author hbx
 * @since 2024-07-20
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserInfoMapper userInfoMapper;
    
    @Autowired
    private loginUserFeignClient authClient;

    @Override
    public AjaxResult sendRegisterVerifyCode(String phone) {
        //1 校验用户是否存在
        List<User> users = userMapper.selectList(new EntityWrapper<User>().eq("phone", phone));
//        RonghuaAssert.isNotNull(users, SystemErrorCode.RESPONSE_CODE_500005);
        if(users.size() != 0)
            throw new BusinessException(SystemErrorCode.RESPONSE_CODE_500005);
        //2 发送短信验证码
        return senSmsCode(phone);
    }

    @Override
    public AjaxResult registerPhone(UserPhoneRegisterDto dto) {
        //1 校验验证码
        String inputValidateCode = dto.getValidateCode();
        //获取redis中的验证码
        String validateCode = getSmsValidateCodeForRegister(dto.getPhone());

        if (StringUtils.isEmpty(validateCode) ||
                !inputValidateCode.equalsIgnoreCase(validateCode))

            return AjaxResult.error("请输入正确验证码",4001);
        //2 远程调用LoginClient完成loginUser添加返回loginId
        LoginUser loginUser = new LoginUser();
        loginUser.setUsername(UUID.randomUUID().toString());
        loginUser.setPassword(dto.getPassword());
        loginUser.setTel(dto.getPhone());
        loginUser.setType(1);
        AjaxResult ajaxResult = authClient.addOrUpdate(loginUser);
        String jsonString = JSON.toJSONString(ajaxResult.getData());
        LoginUser loginUserInfo = JSONObject.parseObject(jsonString, LoginUser.class);
        Long loginId = loginUserInfo.getId();

        //3 保存用户基本信息
        User user = new User();
        user.setCreateTime(new Date().getTime());
        user.setPhone(dto.getPhone());
        user.setPassword(dto.getPassword());
        user.setSalt(null);
        user.setBitState(1L);
        user.setSecLevel(1);
        user.setLoginId(loginId);
        userMapper.insert(user);
        //4 保存详情
        UserInfo userInfo = new UserInfo();
        userInfo.setRegTime(new Date().getTime());
        userInfo.setLevel(0);
        userInfo.setGrowScore(0);
        userInfo.setUserId(user.getId());
        userInfoMapper.insert(userInfo);
        //5 发送注册成功通知  @TODO

        return AjaxResult.success();
    }

    /**
     * 图形验证码
     * @param imageCodeKey
     * @return
     */
    @Override
    public String getVerifyCodeImage(String imageCodeKey) {
        //生成4位验证码
        String randomString = StrUtils.getComplexRandomString(4);
        System.out.println("图形验证码："+randomString);
        //存入redis
        redisTemplate.opsForValue().set(imageCodeKey,randomString,5, TimeUnit.MINUTES);
        String verifyCode = null;
        try {
            //生成图片，并转为64位加密字符串
            verifyCode = VerifyCodeUtils.VerifyCode(140, 43, randomString);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return verifyCode;
    }

    private String getSmsValidateCodeForRegister(String phone) {
        if(StringUtils.isBlank(phone))
            throw new BusinessException("验证码不能为空");
        String smsCode = (String) redisTemplate.opsForValue().get(SmsContants.REGISTER_SMS_REDIS+phone);
        return smsCode.split(":")[0];
    }

    private AjaxResult senSmsCode(String phone) {
        // 1 参数校验
        // 1.1 参数非空校验
        String redisKey = SmsContants.REGISTER_SMS_REDIS +phone;
        // 2 判断该手机号在redis中有没有验证码
        Object smsCodeByRedis = redisTemplate.opsForValue().get(redisKey);
        String smsCode = "";
        if(Objects.nonNull(smsCodeByRedis)){
            String smsCodeStr = smsCodeByRedis.toString();      // 验证码:发送时间
            smsCode = smsCodeStr.split(":")[0];
            String sendTime = smsCodeStr.split(":")[1];
            // 2.1 如果有,判断是否过了重发时间
            if(System.currentTimeMillis() - Long.parseLong(sendTime) <= 60*1000){
                // 2.1.1 如果没有过重发时间,返回错误信息
                throw new BusinessException(SystemErrorCode.RESPONSE_CODE_500008);
            }
        }else{
            // 2.2 如果手机验证码不存在
            // 2.2.1 重新生成随机字符串作为验证码
            smsCode = VerifyCodeUtils.generateVerifyCode(6);
        }
        // 2.2.2 将验证码存入redis中,并设置过期时间和重发时间
        String value = smsCode+":"+System.currentTimeMillis();
        redisTemplate.opsForValue().set(redisKey,value,5, TimeUnit.MINUTES);

        // 2.2.3 调用短信发送接口发送短信
        String msg = "你的注册验证码是%s,请在5分钟以内使用!";
        //发送验证码 数量有限 不要
//        SmsUtil.sendSms(phone,String.format(msg,smsCode));
        System.out.println(String.format(msg,smsCode));
        return AjaxResult.success();
    }

}
